using Lucene.Net.Analysis;
using Lucene.Net.Analysis.PanGu;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Search;
using Lucene.Net.Store;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using way.model;
using way.service;
using way.util;
using static PanGu.Framework.Lock;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using MenuEntity = way.model.MenuEntity;
using TreeView = System.Windows.Forms.TreeView;

namespace way.view
{
    public partial class MenuView : Form
    {
        //MenuService service = new MenuService(new MenuContext(new DbContextOptionsBuilder().UseMySql(ConfigurationManager.AppSettings["databaseServer"])),);
        public string connectionParameter = string.Empty;
        IMenuService service = InstanceManage.getMenuService();
        MenuCore core = InstanceManage.getMenuCore();
        WinformUtil winformUtil = InstanceManage.getWinformUtil();
        CoreUtil coreUtil = InstanceManage.getCoreUtil();
        //
        Result<List<string>> menuTables = new();
        TreeNode selectNode = new();
        MenuEntity selectEntity=new();
        MenuEntity newAreaEntity=new();
        int queryAroundOfId = 0;
        private int supplementNodeFlag = 0;
        private int queryMenuType = 0;//1标题，2方法
        private string tableNow = string.Empty;
        Dictionary<int, MenuEntity> map_id_entity = [];//异常备用
        Dictionary<int, List<MenuEntity>> map_up_entitys = [];//异常备用
        Dictionary<int, MenuEntity> map_id_method = [];
        Dictionary<int, List<MenuEntity>> map_up_methods = [];
        Dictionary<int, List<MenuEntity>> map_up_menus_top = [];
        Dictionary<int, List<MenuEntity>> map_up_menus_bottom = [];
        Dictionary<string, List<TreeNode>> map_name_treeNodes = [];
        Dictionary<int, TreeNode> map_id_node = [];
        List<MenuEntity> menuHeads = [];
        List<MenuEntity> menuHeadsAround = [];
        List<MenuEntity> menuHeadsTop = [];
        List<MenuEntity> menuHeadsBottom = [];

        //
        MenuInCoreView menuInCoreView;
        string _indexDirPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "LuceneIndex");
        IndexWriter _indexWriter;
        private bool _isProcessingScroll = false;
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern int GetScrollPos(IntPtr hWnd, int nBar);


        public MenuView()
        {
            InitializeComponent();
            initCompoent();
            initPageLocation();
            initAttribute();
            initTable();
            initMethodMenu();
            initTitleMenu();
            initInCoreView();
            //initNodePrevious();
        }
        public void InitLuceneIndex()
        {
            Lucene.Net.Store.Directory indexDir = null;
            IndexWriter writer = null;
            try
            {
                indexDir = FSDirectory.Open(_indexDirPath);
                Analyzer analyzer = new PanGuAnalyzer();
                writer = new IndexWriter(indexDir, analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED);
                foreach (var kvp in map_name_treeNodes)
                {
                    foreach (var node in kvp.Value)
                    {
                        var doc = new Lucene.Net.Documents.Document();
                        doc.Add(new Field("Name", kvp.Key, Field.Store.YES, Field.Index.NOT_ANALYZED));
                        doc.Add(new Field("NodeId", node.Name, Field.Store.YES, Field.Index.NOT_ANALYZED));
                        doc.Add(new Field("Text", node.Text, Field.Store.YES, Field.Index.NOT_ANALYZED));
                        writer.AddDocument(doc);
                    }
                }
                writer.Commit();
            }
            catch (Exception ex)
            {
                messageShow(ex.Message, Color.Red);
            }
            finally
            {
                if (indexDir != null)
                {
                    indexDir.Dispose();
                }
                if (writer != null)
                {
                    writer.Dispose();
                }
            }
        }
        public List<int> searchNodeIdsByWildcardName(string name)
        {
            var result = new List<int>();
            using var dir = FSDirectory.Open(new DirectoryInfo(_indexDirPath));
            using var reader = IndexReader.Open(dir, true);
            var searcher = new IndexSearcher(reader);
            var term = new Term("Name", $"*{name}*");
            var query = new WildcardQuery(term);
            var topDocs = searcher.Search(query, 100);
            foreach (var scoreDoc in topDocs.ScoreDocs)
            {
                var doc = searcher.Doc(scoreDoc.Doc);
                result.Add(int.Parse(doc.Get("NodeId")));
            }
            return result;
        }
        private void initInCoreView()
        {
            menuInCoreView = new();
        }
        private void initCompoent()
        {
            this.KeyPreview = true;
            this.treeViewTitle.MouseWheel += treeViewTitle_MouseWheel;
            //this.KeyDown += new KeyEventHandler(MenuView_KeyDown);
        }
        private void initAttribute()
        {
            connectionParameter = ConfigurationManager.AppSettings["databaseServer"] ?? core.titleMenu;
        }
        private void initPageLocation()
        {
            int ScreenWidth = Screen.PrimaryScreen.WorkingArea.Width;
            int ScreenHeight = Screen.PrimaryScreen.WorkingArea.Height;
            //int x = (int)ScreenWidth/3*2 - (int)this.Width/2 - 5;
            int x = (ScreenWidth - this.Width) / 10 * 10 - 5;
            int y = ScreenHeight - this.Height - 5;
            this.Location = new Point(x, y);
        }
        #region treeview
        private void initNodePrevious()
        {
            Result<MenuEntity> res = new Result<MenuEntity>() { table = comboBoxTable.Text };
            string name = ConfigTool.getAppConfigSetting(core.appConfigMenuNodePrevious);
            if (string.IsNullOrWhiteSpace(name)) { return; }
            string[] ids = name.Split(',');
            MenuEntity entity = null;
            foreach (var id in ids)
            {
                res.id = Convert.ToInt32(id);
                service.queryMenuById(res);
                if (res.data != null)
                {
                    entity = res.data;
                    break;
                }
            }
            if (entity == null)
            {
                return;
            }
            if (map_name_treeNodes.ContainsKey(entity.name))
            {
                var list = map_name_treeNodes[entity.name];
                foreach (var item in list)
                {
                    MenuEntity entity1 = (MenuEntity)item.Tag;
                    if (entity1.id == entity.id)
                    {
                        treeViewTitle.SelectedNode = item;
                        item.EnsureVisible();
                    }
                }
            }
        }

        private void initTable()
        {
            /**
         * parameter: string key
         * Result: table, schema, 
         */
            menuTables.table = core.titleMenu;
            menuTables.schema = ConfigTool.getAppConfigSetting(core.appConfigDataBase);
            service.searchTableByKeyword("%" + core.titleMenu + "%", menuTables);
            comboBoxTable.Items.AddRange(menuTables.data.ToArray());
        }
        //private void initTreeview(Dictionary<int, MenuEntity> menuIdMap, Dictionary<int, List<MenuEntity>> menuUpMap, string table)
        //{
        //    Result<Dictionary<int, MenuEntity>> res = new Result<Dictionary<int, MenuEntity>>();
        //    res.data = menuIdMap;
        //    comboBoxTable.Text = table;
        //    res = queryMenu(res);
        //    if (res.check()) { messageShow(res); return; }
        //    menuIdMap = res.data;
        //    //
        //    Result<Dictionary<int, List<MenuEntity>>> req = new Result<Dictionary<int, List<MenuEntity>>>();
        //    req.data = menuUpMap;
        //    req = sortMenuIdMap(res, req);
        //    if (req.check()) { messageShow(res); return; }
        //    menuUpMap = req.data;
        //    freshHeadMenu(treeViewTitle, menuUpMap, 1);
        //}
        private void clear()
        {
            //以下保持数量一致
            map_id_entity.Clear();
            map_id_node.Clear();
            map_name_treeNodes.Clear();
            map_up_entitys.Clear();
            //
            map_up_menus_top.Clear();
            map_up_menus_bottom.Clear();
        }
        private Result<Dictionary<int, MenuEntity>> initTitleMenu()
        {
            //初始化
            Result<Dictionary<int, MenuEntity>> res = new();
            res.table = tableNow;
            res.data = map_id_entity;
            res.id = queryAroundOfId;
            //调用返回检查状态是否正常
            queryMenuType = 1;
            if (queryMenu(res).check()) { messageShow(res); return res; }

            //id_menu => up_childs, sort up
            Result<Dictionary<int, List<MenuEntity>>> req = new()
            {
                data = map_up_entitys
            };
            if (sortMenuIdMap(res, req).check()) { messageShow(req); return res; }


            //渲染
            Result<TreeNode> res1 = freshHeadMenu(treeViewTitle, req.data, queryMenuType);
            if (res1.check())
            {
                //supplementNodeFlag = 0;
                //if (freshHeadMenu(treeViewTitle, req.data, queryMenuType).check())
                //{
                //    clear();
                //    return res.setStatus(res1);
                //}
                return res.setStatus(res1);
            }
            //替换top或bottom（补充上则top，反之）
            if (supplementNodeFlag == 1)
            {
                map_up_menus_top = req.data;
            }
            else if (supplementNodeFlag == 2)
            {
                map_up_menus_bottom = req.data;
            }
            //id_menu add( new id_menu)
            //if (supplementNodeFlag == 0)
            //{
            //    map_id_entity = res.data;
            //    map_up_entitys = req.data;
            //}
            else
            {
                //map_id_entity和map_id_node是一致的，选择后者好点
                //foreach (var item in res.data.Values)
                //{
                //    if (!map_id_entity.ContainsKey(item.id))
                //    {
                //        map_id_entity.Add(item.id, item);
                //    }
                //}
                //foreach (var item in req.data)
                //{
                //    if (!map_up_entitys.ContainsKey(item.Key))
                //    {
                //        map_up_entitys.Add(item.Key, item.Value);
                //    }
                //    else
                //    {
                //        Dictionary<int, MenuEntity> dic = map_up_entitys[item.Key].ToDictionary(m => m.id);
                //        foreach (var item1 in item.Value)
                //        {
                //            if (!dic.ContainsKey(item1.id)) {
                //                map_up_entitys[item.Key].Add(item1);//后续插入新的节点，需要根据此存在来决定，其实如果已经存在，则不会操作，所以这步没必要
                //            }
                //        }
                //    }
                //}
            }
            return res;
        }

        private Result<string> initMethodMenu()
        {
            Result<string> result = new();
            Result<Dictionary<int, MenuEntity>> res = new() { data = map_id_method };
            comboBoxTable.Text = core.methodMenu;
            queryMenuType = 2;
            if (queryMenu(res).check()) { return result.setStatus(res); }
            //map_id_method = res.data;
            Result<Dictionary<int, List<MenuEntity>>> req = new Result<Dictionary<int, List<MenuEntity>>>();
            req.data = map_up_methods;
            if (sortMenuIdMap(res, req).check()) { messageShow(req); return result.setStatus(req); }
            if (req.data.ContainsKey(core.upHead)) { menuHeads = req.data[core.upHead]; } else { return result.setStatus(req); }
            if (freshHeadMenuMethod(treeViewMethod, req, queryMenuType).check()) { return result.setStatus(req); }
            //map_up_methods = req.data;
            return result.setStatus(req);
        }
        public Result<TreeNode> saveNodeToMap(TreeNode treeNode)
        {
            try
            {
                //TreeNode treeNode = res.data;
                var entity = (MenuEntity)treeNode.Tag;
                //倒排索引name
                var map = map_name_treeNodes;
                var map2 = map_id_node;
                if (map.ContainsKey(entity.name))
                {
                    bool exist = map[entity.name].Any(node => ((MenuEntity)node.Tag).id == entity.id && node == treeNode);
                    if (!exist) { map[entity.name].Add(treeNode); }
                }
                else
                {
                    map.Add(entity.name, [treeNode]);
                }
                //id索引记录树节点，后期快速定位
                if (!map_id_node.ContainsKey(entity.id))
                {
                    map_id_node[entity.id] = treeNode;
                }
            }
            catch (Exception ex) { Result<TreeNode> res = new(); return res.setStatus(ResultCode.exceptionStatus, ex.Message); }
            return null;
        }
        public Result<List<MenuEntity>> savePreviousMenuToAppConfig(int id)
        {
            Result<List<MenuEntity>> res = new Result<List<MenuEntity>>() { table = comboBoxTable.Text, id = id };
            service.queryMenuSurroundsById(res);
            if (res.check()) { return messageShow(res.setStatus(ResultCode.saveFailedAppConfig)); }
            string ids = string.Empty;
            foreach (var item in res.data)
            {
                ids = ids + Convert.ToString(item.id) + core.split;
            }
            ConfigTool.setAppConfigSetting(core.appConfigMenuNodePrevious, ids);
            return res;
        }
        private Result<TreeNode> freshHeadMenu(TreeView treeView, Dictionary<int, List<MenuEntity>> menuUpMap, int type)
        {
            Result<TreeNode> res = new();
            try
            {
                //检查新节点是否存在，且长度是否为空
                if (menuUpMap == null || menuUpMap.Count == 0) { return messageShow(res); }
                //头节点不存在，则无新增节点
                List<MenuEntity> headMenus = null;
                //先判断菜单类型，再判断菜单新增类型
                if (supplementNodeFlag == 0)
                {
                    treeView.Nodes.Clear();
                    clear();
                    headMenus = menuHeads;
                }
                else if (supplementNodeFlag == 1)
                {
                    headMenus = menuHeadsTop;
                }
                else if (supplementNodeFlag == 2)
                {
                    headMenus = menuHeadsBottom;
                }
                else if (supplementNodeFlag == 3)
                {
                    headMenus = menuHeadsAround;
                }
                if (headMenus == null) { return messageShow(res); }
                treeView.BeginUpdate();
                int i = 0;
                //表不同，需要清空数据
                //if (!string.IsNullOrWhiteSpace(tableNow) && !tableNow.Equals(res.table)) { clear(); } else { tableNow = res.table; }
                //遍历根节点集合，先判断up存在于总up中，不存在则插入最上方，存在则归并到对应节点通过id_node
                foreach (var menu in headMenus)
                {
                    TreeNode node = null;
                    //存在节点，则不用再创建,从节点列表获取
                    if (!map_id_node.ContainsKey(menu.id))
                    {
                        node = new()
                        {
                            Name = Convert.ToString(menu.id),
                            //Text = menu.name,
                            Text = $"{menu.level}.{menu.sort} {menu.name}",
                            //Text = $"{menu.up}.{menu.level}.{menu.sort}.{menu.id} {menu.name}",
                            //Text = $"{Convert.ToString(menu.up)}_{Convert.ToString(menu.sort)}_{Convert.ToString(menu.level)}_{Convert.ToString(menu.id)} {Convert.ToString(menu.name)}",
                            Tag = menu
                        };
                        //类别是否存在，
                        if (map_id_node.ContainsKey(menu.up))
                        {
                            //存在时再判断自身是否存在，不存在才加入
                            if (supplementNodeFlag == 1)
                            {
                                map_id_node[menu.up].Nodes.Insert(0, node);//倒序插入
                            }
                            else
                            {
                                map_id_node[menu.up].Nodes.Add(node);
                            }
                        }
                        else if (supplementNodeFlag == 1)
                        {
                            //独立，且顶部向上，降序扩散
                            if (supplementNodeFlag == 1)
                            {
                                treeView.Nodes.Insert(0, node);//倒序插入
                            }
                            else
                            {
                                treeView.Nodes.Add(node);
                            }
                        }
                        else
                        {
                            treeView.Nodes.Add(node);//独立，且底部向下，升序扩散
                        }
                        //标题型菜单节点记录
                        saveNodeToMap(node);
                    }
                    else
                    {
                        node = map_id_node[menu.id];
                    }
                    //节点存在子节点，需要结合新增节点类型插入到指定位置
                    if (menuUpMap.ContainsKey(menu.id))
                    {
                        Result<TreeNode> res1 = freshSecondToNthMenu(treeView, node, menuUpMap[menu.id], menuUpMap, type);
                        if (res1 != null) { return res.setStatus(ResultCode.exceptionStatus); }
                    }
                }
                treeView.EndUpdate();
                treeView.ExpandAll();
                if (type == 1)
                {
                    //initNodePrevious();
                    //InitLuceneIndex();
                }
            }
            catch (Exception ex)
            {
                return res.setStatus(ResultCode.exceptionStatus);
            }
            return res;
        }
        private Result<TreeNode> freshSecondToNthMenu(TreeView treeView, TreeNode node, List<MenuEntity> childMenus, Dictionary<int, List<MenuEntity>> menuUpMap, int type)
        {
            for (int i = 0; i < childMenus.Count; i++)
            {
                MenuEntity menu = childMenus[i];
                TreeNode nodeChild = null;
                if (!map_id_node.ContainsKey(menu.id))
                {
                    nodeChild = new TreeNode
                    {
                        Name = Convert.ToString(menu.id),
                        //Text = menu.name,
                        //Text = Convert.ToString(levelN) + "." + Convert.ToString(i + 1) + " " + menu.name,
                        Text = $"{menu.level}.{menu.sort} {menu.name}",
                        //Text = $"{menu.up}.{menu.level}.{menu.sort}.{menu.id} {menu.name}",
                        Tag = menu
                    };
                    //已分类节点的子节点，依新增节点类型，决定插入规则，为倒序还是升序
                    if (supplementNodeFlag == 1)
                    {
                        node.Nodes.Insert(0, nodeChild);//倒序插入
                    }
                    else
                    {
                        node.Nodes.Add(nodeChild);
                    }
                    Result<TreeNode> res = saveNodeToMap(nodeChild);
                    if (res != null) { return res; }
                }
                else
                {
                    nodeChild = map_id_node[menu.id];
                }
                //父级存在，但是可能子级不存在，需要进一步判断子级
                if (menuUpMap.ContainsKey(menu.id))
                {
                    freshSecondToNthMenu(treeView, nodeChild, menuUpMap[menu.id], menuUpMap, type);
                }
            }
            return null;
        }
        private Result<Dictionary<int, List<MenuEntity>>> freshHeadMenuMethod(TreeView treeView, Result<Dictionary<int, List<MenuEntity>>> res, int type)
        {
            try
            {
                Dictionary<int, List<MenuEntity>> menuUpMap = res.data; if (menuUpMap == null) { return messageShow(res); }
                if (!menuUpMap.ContainsKey(core.upHead))
                {
                    return res.setStatus(ResultCode.menuHeadNoLast);
                }
                List<MenuEntity> headMenus = menuUpMap[core.upHead]; if (headMenus.Count == 0) { return messageShow(res); }
                treeView.Nodes.Clear();
                treeView.BeginUpdate();
                foreach (var menu in headMenus)
                {
                    TreeNode node = new()
                    {
                        Name = Convert.ToString(menu.id),
                        Text = menu.name,
                        //Text = $"{Convert.ToString(menu.up)}_{Convert.ToString(menu.sort)}_{Convert.ToString(menu.level)}_{Convert.ToString(menu.id)} {Convert.ToString(menu.name)}",
                        Tag = menu
                    };
                    treeView.Nodes.Add(node);
                    if (menuUpMap.ContainsKey(menu.id))
                    {
                        Result<TreeNode> res1 = freshSecondToNthMenuMethod(treeView, node, menuUpMap[menu.id], menuUpMap, type);
                        if (res1 != null) { return res.setStatus(ResultCode.exceptionStatus); }
                    }
                }
                treeView.EndUpdate();
                treeView.ExpandAll();

            }
            catch (Exception ex)
            {
                return res.setStatus(ResultCode.exceptionStatus);
            }
            return res;
        }
        private Result<TreeNode> freshSecondToNthMenuMethod(TreeView treeView, TreeNode node, List<MenuEntity> childMenus, Dictionary<int, List<MenuEntity>> menuUpMap, int type)
        {
            //无法预判的异常交给初始调用者捕获即可
            for (int i = 0; i < childMenus.Count; i++)
            {
                MenuEntity menu = childMenus[i];
                TreeNode nodeChild = new TreeNode
                {
                    Name = Convert.ToString(menu.id),
                    Text = menu.name,
                    //Text = Convert.ToString(levelN) + "." + Convert.ToString(i + 1) + " " + menu.name,
                    //Text = $"{Convert.ToString(menu.up)}_{Convert.ToString(menu.sort)}_{Convert.ToString(menu.level)}_{Convert.ToString(menu.id)} {Convert.ToString(menu.name)}",
                    Tag = menu
                };
                node.Nodes.Add(nodeChild);
                if (menuUpMap.ContainsKey(menu.id))
                {
                    freshSecondToNthMenuMethod(treeView, nodeChild, menuUpMap[menu.id], menuUpMap, type);
                }
            }
            return null;
        }
        #endregion
        private void MenuView_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                MethodMenu(textBoxMethod.Text);
            }
            if (e.Alt && e.KeyCode == Keys.W)
            {
                textBoxName.Focus();
                textBoxName.SelectAll();
            }
            //
            if (e.Alt && e.KeyCode == Keys.Q)
            {
                textBoxMethod.Text = nameof(queryMenu);
            }
            if (e.Alt && e.KeyCode == Keys.S)
            {
                textBoxMethod.Text = "sortBeforeToAfter";

            }
            //add
            if (e.Alt && e.KeyCode == Keys.H)
            {
                textBoxMethod.Text = nameof(menuAddHead);
                textBoxName.SelectAll();
                textBoxName.Focus();
            }
            if (e.Alt && e.KeyCode == Keys.C)
            {
                textBoxMethod.Text = nameof(menuAddChild);
                textBoxName.SelectAll();
                textBoxName.Focus();
            }
            if (e.Alt && e.KeyCode == Keys.B)
            {
                textBoxMethod.Text = nameof(menuAddBefore);
                textBoxName.SelectAll();
                textBoxName.Focus();
            }
            if (e.Alt && e.KeyCode == Keys.A)
            {
                textBoxMethod.Text = nameof(menuAddAfter);
                textBoxName.SelectAll();
                textBoxName.Focus();
            }
            //update
            if (e.Alt && e.KeyCode == Keys.U)
            {
                textBoxMethod.Text = nameof(updateMenuNameById);
                textBoxName.SelectAll();
                textBoxName.Focus();
            }
            //change
            if ((e.Alt || e.Control) && e.KeyCode == Keys.D1)
            {
                textBoxSelect.ReadOnly = !textBoxSelect.ReadOnly;
                if (textBoxSelect.ReadOnly)
                {
                    textBoxSelect.BackColor = Color.Lime;
                    textBoxSelect.ForeColor = Color.Black;
                }
                if (!textBoxSelect.ReadOnly)
                {
                    textBoxSelect.BackColor = Color.Black;
                    textBoxSelect.ForeColor = Color.Lime;
                }
            }
            if ((e.Alt || e.Control) && e.KeyCode == Keys.D2)
            {
                textBoxNewArea.Text = textBoxSelect.Text;
            }
            if ((e.Alt || e.Control) && e.KeyCode == Keys.Down)
            {
                textBoxMethod.Text = nameof(changeMenuChild);
                textBoxNewArea.Text = textBoxSelect.Text;
            }
            if ((e.Alt || e.Control) && e.KeyCode == Keys.Right)
            {
                textBoxMethod.Text = nameof(changeMenuAfter);
                textBoxNewArea.Text = textBoxSelect.Text;
            }
            if ((e.Alt || e.Control) && e.KeyCode == Keys.Left)
            {
                textBoxMethod.Text = nameof(changeMenuBefore);
                textBoxNewArea.Text = textBoxSelect.Text;
            }
        }
        public void MethodMenu(string name)
        {
            callMethodByString(name);
            //switch (name)
            //{
            //    case "menuAddHead":
            //        menuAddHead();
            //        break;
            //    case "menuAddChild":
            //        menuAddChild();
            //        break;
            //    case "menuAddAfter":
            //        menuAddAfter();
            //        break;
            //    case "menuAddBefore":
            //        menuAddBefore();
            //        break;
            //    case "menuDeleteOne":
            //        menuDeleteOne();
            //        break;
            //    case "changeMenuBefore":
            //        changeMenuBefore();
            //        break;
            //    case "changeMenuAfter":
            //        changeMenuAfter();
            //        break;
            //    case "changeMenuChild":
            //        changeMenuChild();
            //        break;
            //    case "updateMenuNameById":
            //        updateMenuNameById();
            //        break;
            //    case "queryMenu":
            //        queryMenu();
            //        break;
            //}
        }
        #region service
        public Result<Dictionary<int, MenuEntity>> queryMenu(Result<Dictionary<int, MenuEntity>> res)
        {
            res.table = tableNow;
            if (string.IsNullOrWhiteSpace(res.table))
            {
                return res.setStatus(ResultCode.databaseTableCheckError);
            }
            //查询（非补充）即清空全部索引
            if (queryMenuType == 1)
            {
                if (supplementNodeFlag == 0)
                {
                    clear();
                    service.queryMenuAround(res);
                    menuHeads = res.menuHeads;
                }
                else if (supplementNodeFlag == 1)
                {
                    if (service.queryMenuTop(res).check()) { return messageShow(res); }
                    menuHeadsTop = res.menuHeads;
                }
                else if (supplementNodeFlag == 2)
                {
                    if (service.queryMenuBottom(res).check()) { return messageShow(res); }
                    menuHeadsBottom = res.menuHeads;
                }
                else
                {
                    service.queryMenuAround(res);
                    menuHeadsAround = res.menuHeads;
                }
            }
            else if (queryMenuType == 2)
            {
                service.queryMenu(res);//方法不多，一次性加载
            }
            return res;
        }
        public void queryMenu()
        {
            queryMenuType = 1;
            supplementNodeFlag = 0;
            initTitleMenu();
            messageShow(ResultCode.menuQuerySuccess);
        }
        public Result<Dictionary<int, List<MenuEntity>>> sortMenuIdMap(Result<Dictionary<int, MenuEntity>> req, Result<Dictionary<int, List<MenuEntity>>> res)
        {
            res.message = comboBoxTable.Text;
            service.sortMenuIdMap(req, res);
            return res;
        }
        public void changeMenuChild()
        {
            //data
            Result<bool> res = new Result<bool> { table = comboBoxTable.Text };
            //controller
            service.changeMenuChild(selectEntity.id, newAreaEntity.id, res);
            //message
            if (res.check()) { messageShow(res); return; }
            queryMenu();
            messageShow(res);
        }
        public void changeMenuAfter()
        {
            //data
            Result<bool> res = new Result<bool> { table = comboBoxTable.Text };

            //controller
            service.changeMenuAfter(selectEntity.id, newAreaEntity.id, res);
            //message
            if (res.check()) { messageShow(res); return; }
            queryMenu();
            messageShow(res);
        }
        public void changeMenuBefore()
        {
            //data
            Result<bool> res = new Result<bool> { table = comboBoxTable.Text };
            //controller
            service.changeMenuBefore(selectEntity.id, newAreaEntity.id, res);
            //message
            if (res.check()) { messageShow(res); return; }
            queryMenu();
            messageShow(res);
        }
        public void menuAddBefore()
        {
            //data
            Result<int> res = new Result<int> { table = comboBoxTable.Text };
            //controller
            service.menuAddBefore(selectEntity.id, textBoxName.Text, res);
            //message
            if (res.check()) { messageShow(res); return; }
            queryMenu();
            messageShow(res);
        }
        public void menuAddAfter()
        {
            //data
            Result<int> res = new Result<int> { table = comboBoxTable.Text };
            //controller
            service.menuAddAfter(selectEntity.id, textBoxName.Text, res);
            //message
            if (res.check()) { messageShow(res); return; }
            queryMenu();
            messageShow(res);
        }
        public void menuAddChild()
        {
            //data
            Result<int> res = new Result<int> { table = comboBoxTable.Text };
            //controller
            service.menuAddChild(selectEntity.id, textBoxName.Text, res);
            //message
            if (res.check()) { messageShow(res); return; }
            queryMenu();
            messageShow(res);
        }
        public void menuAddHead()
        {
            //data
            var res = new Result<int> { table = comboBoxTable.Text };
            //controller
            service.menuAddHead(textBoxName.Text, res);
            //message
            if (res.check()) { messageShow(res); return; }
            queryMenu();
            messageShow(res);
        }
        public void updateMenuNameById()
        {
            //data
            Result<int> res = new Result<int> { table = comboBoxTable.Text };
            //controller
            service.updateMenuNameById(selectEntity.id, textBoxName.Text, res);
            //message
            if (res.check()) { messageShow(res); return; }
            queryMenu();
            messageShow(res);
        }
        public void deleteMenuById()
        {
            //data
            Result<int> res = new Result<int> { table = comboBoxTable.Text };
            //controller
            service.deleteMenuById(selectEntity.id, res);
            //message
            if (res.check()) { messageShow(res); return; }
            queryMenu();
            messageShow(res);
        }
        #endregion
        #region util
        private void callMethodByString(string methodName, params object[] parameters)
        {
            if (string.IsNullOrEmpty(methodName)) return;
            try
            {
                Type formType = this.GetType();
                MethodInfo method = formType.GetMethod(methodName, parameters.Select(p => p?.GetType() ?? typeof(object)).ToArray());
                if (method == null)
                {
                    messageShow(ResultCode.methodNotFound + methodName, Color.Red);
                    return;
                }
                method.Invoke(this, parameters);
            }
            catch (Exception ex)
            {
                messageShow(ResultCode.methodNotFound + methodName + ex.Message, Color.Red);
            }
        }
        public Result<T> messageShow<T>(Result<T> result)
        {
            winformUtil.messageShow(result, richTextBoxMessage);
            return result;
        }
        public void messageShow(string message, Color status)
        {
            winformUtil.messageShow(message, status, richTextBoxMessage);
        }
        public void messageShow(ResultCode code)
        {
            winformUtil.messageShow(code, richTextBoxMessage);
        }
        public async Task setTreeNodeColor(TreeNode treeNode, Color select, Color clear, int time)
        {
            treeViewTitle.Invoke(new Action(() =>
            {
                treeNode.ForeColor = select;
            }));
            await Task.Delay(time);
            treeViewTitle.Invoke(new Action(() =>
            {
                treeNode.ForeColor = clear;
            }));
        }
        public void deleteNodeTop() {
            TreeView tree= treeViewTitle;
            List<string> list = [];
            Dictionary<int, TreeNode> mapNode = map_id_node;
            int deleteCount = core.queryLength;
            foreach (TreeNode node in tree.Nodes) {
                if (mapNode.ContainsKey(Convert.ToInt32(node.Name))) {
                    deleteNodeNTop(mapNode, list, node, deleteCount);
                }
                if (list.Count < deleteCount)
                {
                    list.Add(node.Name);
                }
            }
        }
        public void deleteNodeNTop(Dictionary<int, TreeNode> mapNode, List<string> list, TreeNode node,int deleteCount) {
            foreach (TreeNode nodeN in node.Nodes)
            {
                if (mapNode.ContainsKey(Convert.ToInt32(nodeN.Name)))
                {
                    deleteNodeNTop(mapNode, list, nodeN, deleteCount);
                }
                if (list.Count < deleteCount)
                {
                    list.Add(nodeN.Name);
                }
            }
            if (list.Count < deleteCount)
            {
                list.Add(node.Name);
            }
        }
        #endregion
        #region Event
        private void treeViewTitle_MouseWheel(object sender, MouseEventArgs e)
        {
            //if (_isProcessingScroll) return;//防抖，或连续滚动
            //_isProcessingScroll = true;
            //TreeView tv = sender as TreeView;
            //const int SB_VERT = 1;//垂直滚动条标识
            ////当前滚动位置
            //int currentScrollPos = GetScrollPos(tv.Handle, SB_VERT);
            ////计算滚动条最大范围
            //int maxScrollPos = 0;
            //if (tv.Nodes.Count > 0)
            //{
            //    //获取最后一个顶级节点的底座坐标，减去控件显示高度=最大滚动值
            //    var lastNode = tv.Nodes[tv.Nodes.Count - 1];
            //    maxScrollPos = lastNode.Bounds.Bottom - tv.ClientSize.Height;
            //    maxScrollPos = Math.Max(maxScrollPos, 0);
            //}
            //bool isTop = currentScrollPos <= 0 && e.Delta > 0;//向上滚轮+滚动到顶
            //bool isBottom = currentScrollPos >= maxScrollPos - 10 && e.Delta < 0;
            //try
            //{
            //    if (isTop)
            //    {
            //        initMenu();
            //        MessageBox.Show("已触顶，执行刷新逻辑");
            //        #region 已触顶，执行刷新逻辑
            //        //获取数据
            //        Result<Dictionary<int, MenuEntity>> res = new Result<Dictionary<int, MenuEntity>>();
            //        res.data = map_id_entity;
            //        res.table = core.titleMenu;
            //        res.id = 214;
            //        service.queryMenuTop(res);
            //        //绘制树节点，且保存树


            //        #endregion
            //        ((HandledMouseEventArgs)e).Handled = true;//取消默认滚动
            //    }
            //    else if (isBottom)
            //    {
            //        MessageBox.Show("已触底，执行刷新逻辑");
            //        #region 已触底，执行刷新逻辑

            //        #endregion
            //        ((HandledMouseEventArgs)e).Handled = true;//取消默认滚动
            //    }
            //}
            //finally
            //{
            //    System.Threading.Thread.Sleep(500);
            //    _isProcessingScroll = false;
            //}
        }
        private void treeViewMethod_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            MenuEntity menu = (MenuEntity)e.Node.Tag;
            textBoxMethod.Text = menu.name;
        }
        private void treeViewTitle_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            var entity = (MenuEntity)e.Node.Tag;
            if (textBoxSelect.ReadOnly)
            {
                newAreaEntity = entity;
                textBoxNewArea.Text = newAreaEntity.name;
                return;
            }
            selectNode = e.Node;
            selectEntity = entity;
            textBoxSelect.Text = selectEntity.name;
            selectEntity.table = comboBoxTable.Text;
            savePreviousMenuToAppConfig(selectEntity.id);
            queryAroundOfId = selectEntity.id;
            if ((Control.ModifierKeys & Keys.Alt) == Keys.Alt)
            {
                menuInCoreView.LoadData(selectEntity);
                menuInCoreView.Show();
            }
            if ((Control.ModifierKeys & Keys.Control) == Keys.Control)
            {
                supplementNodeFlag = 3;//展示100个子节点
                initTitleMenu();
            }
        }
        private void textBoxName_KeyPress(object sender, KeyPressEventArgs e)
        {
            //if (e.KeyChar == (char)Keys.Enter)
            //{
            //    MethodMenu(textBoxMethod.Text);
            //}
        }
        private void textBoxNewArea_TextChanged(object sender, EventArgs e)
        {
            //newAreaEntity = seletEntity;
        }

        private void textBoxSearch_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData != Keys.Enter) { return; }
            string searchKey = textBoxSearch.Text;
            if (string.IsNullOrWhiteSpace(searchKey)) { return; }
            List<int> ids = searchNodeIdsByWildcardName(searchKey);
            if (ids.Count < 1)
            {
                messageShow(ResultCode.dataSelectNull); return;
            }
            comboBoxSearchResult.Items.Clear();
            foreach (var id in ids)
            {

                if (map_id_entity.ContainsKey(id))
                {
                    comboBoxSearchResult.Items.Add(map_id_entity[id].name);
                }
            }
            if (comboBoxSearchResult.Items.Count > 0)
            {
                comboBoxSearchResult.Text = comboBoxSearchResult.Items[0].ToString();
                comboBoxSearchResult_DropDownClosed(null, null);
            }

        }
        private void comboBoxSearchResult_MouseClick(object sender, MouseEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(comboBoxSearchTreeNode.Text))
            {
                return;
            }
            comboBoxSearchResult_TextChanged(null, null);
        }
        private void comboBoxSearchResult_TextChanged(object sender, EventArgs e)
        {
            string value = comboBoxSearchResult.Text;
            if (map_name_treeNodes.ContainsKey(value))
            {
                List<TreeNode> treeNodes = map_name_treeNodes[value];
                comboBoxSearchTreeNode.Items.Clear();
                for (int i = 0; i < treeNodes.Count; i++)
                {
                    comboBoxSearchTreeNode.Items.Add(i.ToString() + "," + treeNodes[i].Name + "=>" + treeNodes[i].Text);
                }
                if (treeNodes.Count > 0)
                {
                    comboBoxSearchTreeNode.Text = comboBoxSearchTreeNode.Items[0].ToString();
                    comboBoxSearchTreeNode_DropDownClosed(null, null);
                }
            }
        }
        private void comboBoxSearchResult_DropDownClosed(object sender, EventArgs e)
        {
            int index = comboBoxSearchResult.SelectedIndex;
            string value = comboBoxSearchResult.Items[index].ToString();
            if (map_name_treeNodes.ContainsKey(value))
            {
                List<TreeNode> treeNodes = map_name_treeNodes[value];
                comboBoxSearchTreeNode.Items.Clear();
                for (int i = 0; i < treeNodes.Count; i++)
                {
                    comboBoxSearchTreeNode.Items.Add(i.ToString() + "," + treeNodes[i].Name + "=>" + treeNodes[i].Text);
                }
                if (treeNodes.Count > 0)
                {
                    comboBoxSearchTreeNode.Text = comboBoxSearchTreeNode.Items[0].ToString();
                    comboBoxSearchTreeNode_DropDownClosed(null, null);
                }
            }
        }
        private async void comboBoxSearchTreeNode_MouseClick(object sender, MouseEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(comboBoxSearchTreeNode.Text))
            {
                return;
            }
            comboBoxSearchTreeNode_TextChanged(null, null);
        }
        private async void comboBoxSearchTreeNode_TextChanged(object sender, EventArgs e)
        {

            int index = Convert.ToInt32(comboBoxSearchTreeNode.Text.Split(',')[0]);
            string value = comboBoxSearchTreeNode.Text.Split("=>")[1];
            if (map_name_treeNodes.ContainsKey(value))
            {
                treeViewTitle.SelectedNode = map_name_treeNodes[value][index];
                treeViewTitle.SelectedNode.EnsureVisible();

                await setTreeNodeColor(treeViewTitle.SelectedNode, Color.Lime, Color.White, 1000);
            }
        }
        private async void comboBoxSearchTreeNode_DropDownClosed(object sender, EventArgs e)
        {
            int index = comboBoxSearchTreeNode.SelectedIndex;
            string value = comboBoxSearchTreeNode.Items[index].ToString().Split("=>")[1];
            if (map_name_treeNodes.ContainsKey(value))
            {
                treeViewTitle.SelectedNode = map_name_treeNodes[value][index];
                treeViewTitle.SelectedNode.EnsureVisible();

                await setTreeNodeColor(treeViewTitle.SelectedNode, Color.Lime, Color.White, 1000);
            }
        }

        private void comboBoxTable_DropDownClosed(object sender, EventArgs e)
        {
            int i = comboBoxTable.SelectedIndex;
            if (i < 0)
            {
                return;
            }
            string str = comboBoxTable.Items[i].ToString();
            if (string.IsNullOrWhiteSpace(str))
            {
                return;
            }
            ConfigTool.setAppConfigSetting(core.appConfigUseTable, str);
        }
        private void button_top_Click(object sender, EventArgs e)
        {
            supplementNodeFlag = 1;//顶部扩展100个节点
            initTitleMenu();
        }

        private void button_bottom_Click(object sender, EventArgs e)
        {
            supplementNodeFlag = 2;
            initTitleMenu();
        }
        private void comboBoxTable_TextChanged(object sender, EventArgs e)
        {
            queryMenuType = 1;
            supplementNodeFlag = 0;
            queryAroundOfId = 0;
            selectEntity = new();
            newAreaEntity = new();
            map_up_menus_bottom = [];
            map_name_treeNodes = [];
            map_id_node = [];
            treeViewTitle.Nodes.Clear();
            tableNow = comboBoxTable.Text;
            //clear();
        }
        #endregion
    }
}
